package com.seafood.service.impl;

import com.seafood.dto.CategoryDTO;
import com.seafood.entity.Category;
import com.seafood.repository.CategoryRepository;
import com.seafood.service.CategoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 分类服务实现类
 */
@Service
@RequiredArgsConstructor
@Transactional
public class CategoryServiceImpl implements CategoryService {
    
    private final CategoryRepository categoryRepository;
    
    @Override
    @Transactional(readOnly = true)
    public List<CategoryDTO> getTopCategories() {
        List<Category> categories = categoryRepository.findByParentIdIsNullAndStatusOrderBySortOrder(
                Category.CategoryStatus.ACTIVE);
        return categories.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<CategoryDTO> getCategoriesByParentId(Long parentId) {
        List<Category> categories = categoryRepository.findByParentIdAndStatusOrderBySortOrder(
                parentId, Category.CategoryStatus.ACTIVE);
        return categories.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<CategoryDTO> getAllCategoriesTree() {
        List<CategoryDTO> topCategories = getTopCategories();
        
        // 递归构建树形结构
        for (CategoryDTO category : topCategories) {
            buildCategoryTree(category);
        }
        
        return topCategories;
    }
    
    /**
     * 递归构建分类树
     */
    private void buildCategoryTree(CategoryDTO category) {
        List<CategoryDTO> children = getCategoriesByParentId(category.getId());
        if (!children.isEmpty()) {
            category.setChildren(children);
            for (CategoryDTO child : children) {
                buildCategoryTree(child);
            }
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public CategoryDTO getCategoryById(Long id) {
        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("分类不存在"));
        return convertToDTO(category);
    }
    
    @Override
    public CategoryDTO createCategory(CategoryDTO categoryDTO) {
        // 检查同级分类名称是否重复
        boolean exists = categoryRepository.existsByNameAndParentId(
                categoryDTO.getName(), categoryDTO.getParentId());
        if (exists) {
            throw new RuntimeException("同级分类中已存在相同名称的分类");
        }
        
        Category category = convertToEntity(categoryDTO);
        category.setStatus(Category.CategoryStatus.ACTIVE);
        
        Category savedCategory = categoryRepository.save(category);
        return convertToDTO(savedCategory);
    }
    
    @Override
    public CategoryDTO updateCategory(Long id, CategoryDTO categoryDTO) {
        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("分类不存在"));
        
        // 检查名称是否与其他同级分类重复
        if (!category.getName().equals(categoryDTO.getName())) {
            boolean exists = categoryRepository.existsByNameAndParentId(
                    categoryDTO.getName(), categoryDTO.getParentId());
            if (exists) {
                throw new RuntimeException("同级分类中已存在相同名称的分类");
            }
        }
        
        // 更新字段
        category.setName(categoryDTO.getName());
        category.setDescription(categoryDTO.getDescription());
        category.setSortOrder(categoryDTO.getSortOrder());
        
        if (categoryDTO.getStatus() != null) {
            category.setStatus(Category.CategoryStatus.valueOf(categoryDTO.getStatus()));
        }
        
        Category savedCategory = categoryRepository.save(category);
        return convertToDTO(savedCategory);
    }
    
    @Override
    public void deleteCategory(Long id) {
        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("分类不存在"));
        
        // 检查是否有子分类
        List<Category> children = categoryRepository.findByParentIdAndStatusOrderBySortOrder(
                id, Category.CategoryStatus.ACTIVE);
        if (!children.isEmpty()) {
            throw new RuntimeException("该分类下存在子分类，无法删除");
        }
        
        // 检查是否有产品使用该分类
        if (category.getProducts() != null && !category.getProducts().isEmpty()) {
            throw new RuntimeException("该分类下存在产品，无法删除");
        }
        
        // 软删除：更改状态为INACTIVE
        category.setStatus(Category.CategoryStatus.INACTIVE);
        categoryRepository.save(category);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<CategoryDTO> searchCategoriesByName(String name) {
        List<Category> categories = categoryRepository.findByNameContaining(
                name, Category.CategoryStatus.ACTIVE);
        return categories.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Override
    public CategoryDTO convertToDTO(Category category) {
        CategoryDTO dto = new CategoryDTO();
        dto.setId(category.getId());
        dto.setName(category.getName());
        dto.setDescription(category.getDescription());
        dto.setParentId(category.getParentId());
        dto.setSortOrder(category.getSortOrder());
        dto.setStatus(category.getStatus().name());
        
        if (category.getCreatedAt() != null) {
            dto.setCreatedAt(category.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }
        
        // 统计产品数量
        if (category.getProducts() != null) {
            dto.setProductCount((long) category.getProducts().size());
        } else {
            dto.setProductCount(0L);
        }
        
        return dto;
    }
    
    @Override
    public Category convertToEntity(CategoryDTO categoryDTO) {
        Category category = new Category();
        category.setName(categoryDTO.getName());
        category.setDescription(categoryDTO.getDescription());
        category.setParentId(categoryDTO.getParentId());
        category.setSortOrder(categoryDTO.getSortOrder() != null ? categoryDTO.getSortOrder() : 0);
        
        return category;
    }
}